perm filename PASFUN[1,RWF] blob
sn#730323 filedate 1983-11-02 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00002 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 Pascal Functions and Procedures
C00017 ENDMK
C⊗;
Pascal Functions and Procedures
Pascal embodies several ways of incorporating subalgorithms into programs.
Subalgorithms which compute a single value are best expressed as _functions_
in Pascal, while subalgorithms which compute several values (or none) are
best expressed as Pascal _procedures_. Rather than describe these subalgorithms
in their full generality, I will first describe restricted forms that lend
themselves to disciplined programming: _pure_ functions and procedures.
A pure function in Pascal is a subalgorithm which takes a fixed number of
input values (each required to be of a specified type), carries out a
computation which interacts with its master algorithm only through inspection
of the input values, and returns to the master algorithm a single value of a
specified type.
Here is an example of a Pascal function definition:
FUNCTION H (A:INTEGER;B:INTEGER):REAL;
VAR I:INTEGER;S:REAL;
BEGIN
S:=0.0;
FOR I:=A TO B DO
S:=S+1/I;
H:=S
END
This function is a subalgorithm which is executed after values have been given
to A and B; it adds 1/A, 1/(A+1), 1/(A+2),..., 1/B, and returns the sum to the
master program.
The general form of a function definition is
FUNCTION function parameter type
identifier ( identifier , : identifier ;
) : type ; block ;
identifier
Within the block, the parameters (e.g., A and B) are used like storage variables.
The name of the function (e.g., H) is used within the function block as a result
variable, to which an assignment must be made before completion of the block.
************** Define blocks
In a _pure_ function, no use is made of variables or parameters other than those
belonging to the function itself. This implies that information enters the
function only through parameters, and leaves only through the result variable.
A function definition appears in the subprogram declaration section of its
master program. The defined function may be used in the block of its master
program, and also in any subprogram definitions that follow it in the same
subprogram declaration section.
Pascal functions are used in expressions, in much the same way that builtin
functions like COS and ABS are used. If F is the name of the function, and
E↓1,E↓2,...E↓n are expressions for its arguments (input values), then
F(E↓1,E↓2,...,E↓n) is a function call, an expression whose value is found by
executing the function. The arguments must be assignable to the corresponding
parameters of the function; ordinarily this means the types are the same.
The function is executed by evaluating the arguments, giving their respective
values to the parameters, and executing the body of the function. The function
body must assign a value to its result variable. When it finishes, the value
of its result variable is taken as the value of the function call.
The use of functional notation for function calls makes it easy to use the result
of one function as an argument to another. To evaluate g(x,y) with result r,
and then to evaluate f(z,r), requires only writing the expression f(z,g(x,y));
the intermediate result does not have to be given a name (like r) in the program.
To trace the action of a function call, we draw a new contour. Suppose the
function H is called in the context
WRITE(H(P,Q-1)/(P-Q)) with P = 2, Q = 5. First we evaluate the
arguments, P = 2, Q-1 = 4. We write down the function call with the
constant arguments
H(2,4)
and open a contour box, with the arguments assigned to
the parameters (A=2,B=4), the ordinary variables of the function
undefined (I=?,S=?) and the result variable undefined (H=?).
We now have
H(2,4)
A = 2
B = 4
I = ?
S = ?
H = ?
and proceed to execute the function.
S:= 0.0
S = 0.0
FOR I:=2 TO 4
I = 2
S:=0.0+ 1/2
S =0.5
I = 3
S:=0.5+ 1/3
S =0.83
I = 4
S:=0.83+ 1/4
S =1.07
I = 5
I = ?
H:= 1.07
H = 1.07
H(2,4) = 1.07
When finished, we close the contour box, and copy the value of the result variable,
as shown above. We then continue in the master algorithm, using that result as
the value of the function call:
WRITE(1.07/(5-2)) 0.36
A function may be a subprogram to the main program, but it may also be a
subprogram to another subprogram. If function F is a subprogram of of function
G, its definition appears in the subprogram declarations section of the
definitions of G.
What we have described as a pure function interacts with its master program
only through its parameters and result variable. Other kinds of interaction
are allowed by Pascal, as we shall see later, but for 90% of the applications
of functions, a pure function is most satisfactory. In particular, a program
where functions are pure is easier to understand and debug.
Subprograms with exactly one result are readily designed as Pascal functions.
Subprograms with no results, or with several, ae better designed as _procedures_.
The principal difference is that a call on a function is an expression which
executes the function and stands for the result; a call on a procedure is a
command, which executes the procedure, but does not stand for a result.
Here is an example of a Pascal procedure, with no result.
PROCEDURE SQUARE (N:INTEGER;C:CHAR);
VAR I,J:INTEGER;
BEGIN
WRITELN;
FOR I:=1 TO N DO
BEGIN
FOR J:=1 TO N DO
WRITE(C);
WRITELN
END
END;
This procedure is a subalgorithm which is executed after values have been given
to N and C; it prints an N-by-N square of the character C, and then returns to
the master program. A call SQUARE(4,'*') would print
****
****
****
****
If a parameter or set of parameters of a procedure or function is preceded by
the word VAR, the parameters are variables; the subprogram may, by assigning
values to them, assign those values to the corresponding arguments in the
master program. Arguments corresponding to variable parameters must be variables.
Here is an example procedure to find both roots of an equation AX↑2+BX+C=0,
PROCEDURE QUADRATIC (A,B,C:REAL;VAR ROOT1,ROOT2:R REAL);
VAR D;
BEGIN
D:=SQRT(B*B-4*A*C);
ROOT1:= (-B+D)/(2*A);
ROOT2:= (-B-D)/(2*A)
END
The call
QUADRATIC(2,-3,1,X,Y)
followed by
WRITE(X,Y)
will print __________________.
********** FILL IN
The general form of a pure procedure definition is
PROCEDURE procedure
identifier
( parameter , type ; ) ;
identifier identifier
VAR :
Block ;
Within the block, the parameters are used like storage variables. Variable
parameters are not distinct from their arguments; an assignment to a variable
parameter is an assignment to the argument variable. This is the way to return
results to the master algorithm. In a pure procedure, no use is made of
variables or parameters other than those belonging to the function itself.
This implies that information enters the procedure only through parameters,
and leaves only through variable parameters.
A pure function is very easy to test separately from the rest of the program.
If it works with numbers as arguments, we can try it with constant arguments
C1,C2,...Cn by incorporating the function definition in this program:
PROGRAM....(OUTPUT);
definition of function F;
BEGIN
WRITELN(C1,C2,...,Cn,F(C1,C2,...,Cn))
END.
The penultimate line can be repeated with as many different argument values as
needed, or one can iterate:
FOR I:= 1 to N DO
BEGIN
READ(X1,X2,...,XN);
WRITELN(X1,X2,...,XN,F(X1,X2,...,XN)
END
Such a program is called a driver; its only purpose is to test a pure function on
data for which the correct result is known.
Conversely, it is easy to test the main program without the correct definition of
the pure function, replacing the function's definition by some easy function.
If the main program is designed to form the sum F(1)+F(2)+...+F(100), and the
correct definition of F is difficult to program, we can test the summation and
the printing format by using the easy function F(X)=X, this way:
PROGRAM P(OUTPUT);
VAR J:INTEGER;SUM:REAL;
FUNCTION F(I:INTEGER):REAL;
BEGIN
F:=I
END;
BEGIN
SUM:=0.0
FOR J:= 1 TO 100 DO
SUM:= SUM + F(J);
WRITELN(SUM:8:2)
END.
If the program prints 5050.00, we know that the main program is in good shape.
We have tested it using a _stub_ in place of the correct subprogram; a stub goes
through the same motions as the absent subprogram, without necessarily giving
correct answers.
If the test of the master program requires that the subprogram give correct
answers, we can still test with a stub, but the stub now asks the user for help.
The declaration of the stub looks like:
FUNCTION F(X,Y:REAL):REAL;
BEGIN
WRITELN(TTY,'WHAT IS F IF X AND Y ARE',X,Y,'?');
READLN(TTY);
READ(TTY,F);
(* FOR MORE RELIABLE TERMINAL INPUT *)
(* SEE SECTION ON FILES *)
END
Every part of a program under development can be tested separately, by using a
driver to substitute for its master program, and stubs to substitute for its
subprograms. This technique allows a team to subdivide a programming project
in such a way that no bottlenecks impede the testing.
Reference: Aron, The Program Development Process.